package org.zsk.cs.algorithnm.loadbalance.sendorder.impl;

import org.zsk.cs.algorithnm.entity.EmployTask;
import org.zsk.cs.algorithnm.loadbalance.sendorder.LoadBalance;
import org.zsk.cs.algorithnm.loadbalance.sendorder.SendOrderUtil;

import java.util.List;

/**
 * 负载均衡-权重轮询派单
 * @author zsk
 * 2021/4/19 下午4:29
 */
public class WeightRoundRobinLoadBalancer implements LoadBalance<EmployTask> {

    /**上次选择的工号*/
    private int currentIndex = -1;
    /**当前调度的权值*/
    private int currentWeight = 0;
    /**最大权重*/
    private int maxWeight;
    /**权重的最大公约数*/
    private int gcdWeight;
    /**员工数数*/
    private int employCount;

    @Override
    public EmployTask pickOne() {
        List<EmployTask> employTasksInList = SendOrderUtil.getEmployTasksInList();
        while(true){
            currentIndex = (currentIndex + 1) % employCount;
            if(currentIndex == 0){
                currentWeight = currentWeight - gcdWeight;
                if(currentWeight <= 0){
                    currentWeight = maxWeight;
                    if(currentWeight == 0){
                        return null;
                    }
                }
            }
            if(employTasksInList.get(currentIndex).getWeight() >= currentWeight){
                return employTasksInList.get(currentIndex);
            }
        }
    }

    /**
     * 得到两值的最大公约数
     * @param a 第一个数
     * @param b 第二个数
     * @return 最大公约数
     */
    public int greaterCommonDivisor(int a, int b){
        if(a % b == 0){
            return b;
        }else{
            return greaterCommonDivisor(b,a % b);
        }
    }

    /**
     * 得到list中所有权重的最大公约数，实际上是两两取最大公约数d，然后得到的d
     * 与下一个权重取最大公约数，直至遍历完
     * @param employTasks 员工列表
     * @return list中所有权重的最大公约数
     */
    public int greatestCommonDivisor(List<EmployTask> employTasks){
        int divisor = 0;
        for(int index = 0, len = employTasks.size(); index < len - 1; index++){
            if(index ==0){
                divisor = greaterCommonDivisor(
                        employTasks.get(index).getWeight(), employTasks.get(index + 1).getWeight());
            }else{
                divisor = greaterCommonDivisor(divisor, employTasks.get(index).getWeight());
            }
        }
        return divisor;
    }

    /**
     * 得到list中的最大的权重
     * @param employTasks 员工列表
     * @return 最大的权重
     */
    public int greatestWeight(List<EmployTask> employTasks){
        int weight = 0;
        for(EmployTask employTask : employTasks){
            if(weight < employTask.getWeight()){
                weight = employTask.getWeight();
            }
        }
        return weight;
    }

    public void init(){
        List<EmployTask> employTasksInList = SendOrderUtil.getEmployTasksInList();

        maxWeight = greatestWeight(employTasksInList);
        gcdWeight = greatestCommonDivisor(employTasksInList);
        employCount = employTasksInList.size();
    }

    public static void main(String args[]){
        WeightRoundRobinLoadBalancer weightRoundRobinLoadBalancer=new WeightRoundRobinLoadBalancer();
        weightRoundRobinLoadBalancer.init();

        for(int i = 0; i < 30; i++){
            EmployTask employTask = weightRoundRobinLoadBalancer.pickOne();
            System.out.println("员工任务:"+employTask);
        }
    }
}
